import java.util.Map;
import java.util.Set;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.Collections;

import controlP5.ControlEvent;

import processing.core.*;


public class radioGaGa extends PApplet{
	private static final long serialVersionUID = 1L;
	
	private Menu theMenu;
	
	public static View View1;
	public static View View2;
	private View IgnoredArtistsView;
	private View SongSearchView;
	private View HeatView1;
	private View HeatView2;
	private View startView;
	
	//<Phil> (We can move these where seen fit)
	public ArrayList<UserData> UserList;
	public Map<String,UserData> UserMapID;
	public static ArrayList<ArtistData> ArtistList;
	public Map<String,ArtistData> ArtistMapID;
	public String[] currentFile;
	public Filters dataFilter = new Filters();
	
	private boolean setupFinished = false;
	
	public void setup() {
		size(1024, 768);
		
		@SuppressWarnings("unused")
		GLOBAL g = new GLOBAL(this);
		GLOBAL.ALL_COUNTRIES = new ArrayList<String>();
		GLOBAL.fontSegoe = createFont("Segoe UI", 12, true);
		GLOBAL.fontSmall = createFont("standard-7-plain-expanded.ttf", 8, false);
		GLOBAL.HUE = loadImage("hues.gif");
		
		initColors();		//Initialze color variables
		//PARSE .TXT FILES
			parseCountries();
			
		//Initialize Menu
		theMenu = new Menu();
		theMenu.setActiveTab("view1");	//Sets "top artists" view to default
		theMenu.setActiveSex("sex0");	//Sets males + females to default

		background(loadImage("loading.gif"));
		smooth();
	}
	
	public void draw() {
		if(!setupFinished) {
			//<Phil>
			dataSetupFunctions();
			startView = new openingView(180, 50, 1024, 768);
			setupFinished = true;
		}
		
		background(GLOBAL.colorBackground);
		textAlign(LEFT);
		textFont(GLOBAL.fontSegoe, 12);
		noStroke();
		fill(GLOBAL.colorBackground);
		rect(0, 50, 1024, 768);
	
		
		//Top Artist View
		if(GLOBAL.TAB == 0) {
			drawMenuLabels();		//Menu Labels
			
			if(GLOBAL.VIEW_COUNT == 0) {
				startView.draw();
			}
			else if(GLOBAL.VIEW_COUNT == 1) {
				View1.draw();
			} else if(GLOBAL.VIEW_COUNT == 2) {
				View1.draw();
				View2.draw();
			}
		}
		
		//Heat Calendar.
		else if(GLOBAL.TAB == 1) {
			if(GLOBAL.HEATVIEW_COUNT == 1) {
				HeatView1.draw();
			} else if(GLOBAL.HEATVIEW_COUNT == 2) {
				HeatView1.draw();
				if(HeatView2 != null)
					HeatView2.draw();
			}
			
			stroke(GLOBAL.colorMenu);
			line(180, GLOBAL.ViewMidline, 1024, GLOBAL.ViewMidline);
		
			fill(GLOBAL.colorEllipse);
			textSize(14);
			
			text("rectangle", 70, 450);
			text("month", 48, 466);
			text("column", 92, 488);
			text("day", 48, 505);
			text("row", 64, 526);
			text("hour", 54, 542);
			
			fill(0);		
			text("When Do We Jam?", 25, 70);
			
			textSize(12);
			text("HeatCalendar displays how", 10, 90);
			text("often music was played", 20, 105);
			text("down to the hour.", 30, 120);
			
			text("Choose a Year to Display", 10, 160);
			
			text("Each long", 5, 450);
			text("is a", 20, 465);
			text("Wherein, each", 5, 488);
			text("is a", 20, 505);
			text("(Sun-Sat)", 80, 505);
			text("And each", 4, 526);
			text("is an", 20, 542);
			text("(12am-11pm)", 92, 542);

		}
		
		//Song View
		else if(GLOBAL.TAB == 2) {
			SongSearchView.draw();
		}
		
		//Ignored Artists
		else if(GLOBAL.TAB == 3) {
			IgnoredArtistsView.draw();
		}
		
		//The Menu
		fill(GLOBAL.colorMenu);
		rect(0, 0, 1024, 49);	
		GLOBAL.controlP5.draw();
	}
	
	private void parseCountries() {
		String[] rows = loadStrings("countryList.txt");
		
		for(int x=0; x<rows.length; ++x) {
			GLOBAL.ALL_COUNTRIES.add(rows[x]);
		}
	}
	
	private void drawMenuLabels() {
		fill(0);
		text("Age (Range)", 22, 100);
		text("Sex", 22, 160);
		text("Country", 22, 270);
		text("Current Selection :", 4	, 550);
		text("Age : " + GLOBAL.AGE_MIN + " - " + GLOBAL.AGE_MAX, 22, 570);
		text("Sex : " + GLOBAL.getSexString(GLOBAL.SEX), 22, 590);
		text("Country :", 22, 610);
		text(GLOBAL.COUNTRY.replaceAll(" ", "\n"), 80, 610);
		
		textSize(16);
		text("Create A Filter", 30, 74);
		textSize(12);
		
		stroke(GLOBAL.colorMenu);
		line(180, 50, 180, 1024);	//Side Divider
		line(28, 80, 138, 80);
	}
	
	//Initialize colors for GLOBAL.java
	private void initColors() {
		GLOBAL.colorBackground = color(152, 187, 196);
		GLOBAL.colorMenu = color(81, 126, 137);
		GLOBAL.colorTabSelected = color(243, 253, 231);
		GLOBAL.colorTabDeselected = color(208, 229, 176);
		GLOBAL.colorTabMouseOver = color(252, 230, 240);
		GLOBAL.colorListBox = color(182, 215, 220);
		GLOBAL.colorEllipse = color(165, 42, 42); //THIS ONE IS FOR SOUND WAVE (120, 0, 220)
		GLOBAL.colorEllipseHighlight = color(243, 253, 231);
		GLOBAL.colorBarHighlight = color(243, 253, 231);
		GLOBAL.colorFemale = color(233, 143, 179);
		GLOBAL.colorMale = color(140, 190, 255);
		GLOBAL.colorCountry = color(170, 140, 230);
	}

	public static void main(String args[]) {
		PApplet.main(new String[]{"--present --location=0,0", "radioGaGa"});
	}
	
	public void controlEvent(ControlEvent theEvent) {
        if (theEvent.isGroup()) {
        	//Update Selected Artist
        	if(theEvent.group().name().equals("vw_top")) {
        		if(GLOBAL.VIEW_COUNT == 1 || theEvent.group().position().y() < GLOBAL.ViewMidline)
        			View1.handleEvent((int) theEvent.group().value());
        		else 
        			View2.handleEvent((int) theEvent.group().value());
        	}
        	
        	//Update Selected Country
        	else if(theEvent.group().name().equals("countries")) {
        		GLOBAL.COUNTRY = GLOBAL.ALL_COUNTRIES.get((int) theEvent.group().value());
        	}
        } 
        else if(theEvent.isController()) {
            //Update Tabs
            if(theEvent.controller().name().startsWith("view")) {
            	GLOBAL.TAB = theMenu.setActiveTab(theEvent.controller().name());
            	if(GLOBAL.TAB == 3)  {
            		showIgnoredArtists();
            		theMenu.hideFilterMenu();
            		theMenu.setHeatMenuVisibility(false);
            	} else if(GLOBAL.TAB == 2) {
            		showSongSearch();
            		theMenu.hideFilterMenu();
            		theMenu.setHeatMenuVisibility(false);
            	} else if(GLOBAL.TAB == 1) {
            		GLOBAL.VIEW_COUNT = 0;
            		createHeatViews("0");
            		theMenu.hideFilterMenu();
            		theMenu.setHeatMenuVisibility(true);
            	} else {
            		GLOBAL.VIEW_COUNT = 0;
            		theMenu.showAll();
            		theMenu.setHeatMenuVisibility(false);
            	}
            }
            
            //Update sex selection
            else if(theEvent.controller().name().startsWith("sex")) {
            	GLOBAL.SEX = theMenu.setActiveSex(theEvent.controller().name());
            }
            
            //Update Age Range
            else if(theEvent.controller().name().equals("age")) {
            	GLOBAL.AGE_MIN = (int) theEvent.controller().arrayValue()[0];
            	GLOBAL.AGE_MAX = (int) theEvent.controller().arrayValue()[1];
            	theMenu.updateAgeMax();
            }
            
            //Update Country Selection (to 'all')
            else if(theEvent.controller().name().equals("all_cntry")) {
            	GLOBAL.COUNTRY = "All";
            }
            
            //Add Filter
            else if(theEvent.controller().name().equals("add")) {
            	switch(GLOBAL.TAB) {
            	case 0:	createTopViews();
            			break;	
            	}
            }
            
            //Remove a View
            else if(theEvent.controller().name().equals("remove")) {
            	if(View1.mouseOver()) {	//Remove first view
            		if(GLOBAL.VIEW_COUNT == 2)	//Make View2 the full screen
            			View2.resize(180, 50, 1024, 600);
            			View1 = View2;
            	}
            	else {
            		View1.resize(180, 50, 1024, 600);
            	}
            	GLOBAL.VIEW_COUNT--;
            }
            
            //Add A Heat View
            else if(theEvent.controller().name().startsWith("yr")) {
            	createHeatViews(theEvent.controller().name().substring(3));
            }
            
            //View Events
            else if(theEvent.controller().name().startsWith("vw")){
            	if(GLOBAL.TAB == 2)
            		SongSearchView.handleEvent(theEvent.controller().name());
            		
            	else if(GLOBAL.TAB == 3)
            		IgnoredArtistsView.handleEvent(theEvent.controller().name());
            		
            	else if(View1.mouseOver())
        			View1.handleEvent(theEvent.controller().name());
        		else
        			View2.handleEvent(theEvent.controller().name());	
            }
        }
	}
	
	public Filters generateFilter() {
		Filters f = new Filters();
		
			if(!GLOBAL.COUNTRY.equalsIgnoreCase("all") && !GLOBAL.COUNTRY.equals("")) {
				f.addCountry(GLOBAL.COUNTRY);
			}
			
			f.setSexValue(GLOBAL.SEX);
			f.setLowerAgeBound(GLOBAL.AGE_MIN);
			f.setUpperAgeBound(GLOBAL.AGE_MAX);
			f.onOffAge();
			f.onOffSex();
		
		return f;
	}
	
	private void createTopViews() {
		dataFilter = generateFilter();
		artistFilterUpdate();
		Collections.sort(ArtistList);
		
		
		if(GLOBAL.VIEW_COUNT == 0) {
			View1 = new TopView(180, 50, 1024, 600, dataFilter);
			GLOBAL.VIEW_COUNT = 1;
			return;
		}
		
		if(GLOBAL.VIEW_COUNT == 1) {
			View1.resize(180, 50, 1024, GLOBAL.ViewMidline-1);
			View2 = new TopView(180, GLOBAL.ViewMidline, 1024, 768, dataFilter);
			GLOBAL.VIEW_COUNT = 2;
			return;
		}
		

		View2.resize(180, 50, 1024, GLOBAL.ViewMidline-1);
		View1 = View2;
		View2 = new TopView(180, GLOBAL.ViewMidline, 1024, 768, dataFilter);
	}
	
	private void createHeatViews(String yr) {
		int year = Integer.parseInt(yr) + 2000;
		
		if(GLOBAL.HEATVIEW_COUNT == 0) {
			HeatView1 = new HeatView(180, 50, 1024, 768, year);
			GLOBAL.HEATVIEW_COUNT = 1;
			return;
		}
		
		if(GLOBAL.HEATVIEW_COUNT == 1) {
			HeatView1.resize(180, 50, 1024, GLOBAL.ViewMidline-1);
			HeatView2 = new HeatView(180, GLOBAL.ViewMidline, 1024, 768, year);
			GLOBAL.HEATVIEW_COUNT = 2;
			return;
		}
		

		HeatView2.resize(180, 50, 1024, GLOBAL.ViewMidline-1);
		HeatView1 = HeatView2;
		HeatView2 = new HeatView(180, GLOBAL.ViewMidline, 1024, 768, year);
	}
	
	private void showIgnoredArtists() {
		IgnoredArtistsView = new IgnoreView(0, 50, 1024, 768);
	}
	
	private void showSongSearch() {
		SongSearchView = new SongView(0, 50, 1024, 768);
	}
	
	public void dataSetupFunctions()
	{
	    loadUsers();
	    //loadArtist();
	    loadArtistVer2(); //10 files == 2gb...Need to work on the filter.

	    artistFilterUpdate();
	    currentFile = null;

	    giveArtistNames();
	    loadBreakdown();
	    
	    //printTest();
	    removeUseless();
	    printTest();
	    loadHeatData();
	}
	
	public void loadBreakdown() {
		for(int x=0; x<ArtistList.size(); ++x) {
	    	ArtistList.get(x).setupBreakdown();
	    }
	}
	
	public void loadUsers()
	{
	    UserList = new ArrayList<UserData>();
	    UserMapID = new HashMap<String,UserData>();
	    currentFile = loadStrings("userid-profile360.tsv");
	    println("File Length: " + currentFile.length);
	    for(int index=0; index < currentFile.length;index++)
	    {
	        String[] tokens = currentFile[index].split("\t");
	        String someID = "";
	        String someGender = "";
	        String someAge = "";
	        String someCountry = "";
	        String someRegistered = "";
	        
	        //User ID
	        if(tokens[0].isEmpty())
	        {
	            someID = "N";
	        }
	        else
	        {
	            someID = tokens[0];
	        }
	        
	        //User Gender
	        if(tokens[1].isEmpty())
	        {
	            someGender = "N";
	        }
	        else
	        {
	            someGender = tokens[1];
	        }
	        
	        //User Age
	        if(tokens[2].isEmpty())
	        {
	            someAge = "N";
	        }
	        else
	        {
	            someAge = tokens[2];
	        }
	        
	        //User Country
	        if(tokens[3].isEmpty())
	        {
	            someCountry = "N";
	        }
	        else
	        {
	            someCountry = tokens[3];
	        }
	        
	        //User Registered
	        if(tokens[4].isEmpty())
	        {
	            someRegistered = "N";
	        }
	        else
	        {
	            someRegistered = tokens[4];
	        }
	        
	        UserData newUser = new UserData(someID,someGender,someAge,someCountry,someRegistered);
	        newUser.fixEmpty();
	        UserList.add(newUser);
	        //if(newUser.getName().startsWith("6d0")){
	        //System.out.println(newUser.getName() + " --- " + someGender + "\t" + someAge + "\t" + someCountry + "\t" + someRegistered);
	        //}
	        UserMapID.put(newUser.getName(),newUser);
	    }
	}//End of LoadUsers()
	

	
	//Link artist to user
	//public void linkArtistToUser()
	//{
	//    for(int index=0; index < ArtistList.size();index++)
	//    {
	//        ArtistData tempArtist = ArtistList.get(index);
	//        ArrayList<String> tempUserList = tempArtist.getArtistUsers();
	//        for(int index2=0; index2 < tempUserList.size();index2++)
	//        {
	//            UserData tempUser = UserMapID.get(tempUserList.get(index2));
	//            tempArtist.linkUser(tempUser);
	//        }
	//    }
	//}//End of Link artist to user()
	
	//Load Artist names.
	public void giveArtistNames()
	{
		currentFile = loadStrings("MBID.txt");
		for(int index=0; index < currentFile.length; index++)
		{
			String[] token = currentFile[index].split("\t");
			if(ArtistMapID.containsKey(token[1]))
			{
				ArtistData tempArtist = ArtistMapID.get(token[1]);
				tempArtist.setArtistName(token[0]);
			}
		}
	}
	
	public void artistFilterUpdate()
	{
		for(int index=0; index < UserList.size(); index++)
		{
			UserList.get(index).resetFilterCheck();
			UserList.get(index).checkValid(dataFilter);
		}
		for(int index=0; index < ArtistList.size();index++)
		{
			ArtistList.get(index).applyFilters(dataFilter);
		}
	}
	
	//Update Artist Filter
	public void artistFilterUpdatecheck()
	{	
	    for(int index=0; index < ArtistList.size();index++)
	    {
	    	ArtistList.get(index).applyFilters(dataFilter);
	    }
		Collections.sort(ArtistList);
		for(int index=0; index < ArtistList.size();index++)
		{
			//println("Index: " + (index+1) +" || Artist: " + ArtistList.get(index).getName());
		}
		//println("\n\n\n");
		
		Set<String> keys = UserMapID.keySet();
		//println("Number of keys: " + keys.size());
		
		//println("\n\n\n\n");
		int uniquePeople = 0;
		for(int index=0; index < UserList.size();index++)
		{
			UserData tempUser = UserList.get(index);
			if(tempUser.getArtistNumber() >= 1)
			{
				uniquePeople++;
				//println("User: " + tempUser.getName() + " || Number of Artists: " + tempUser.getArtistNumber());

			}
		}
		println("Unique People with at least 1 band: " + uniquePeople);
		println("\n\n\n");
		for(int index=0; index < ArtistList.size();index++)
		{
			ArtistData tempArtist = ArtistList.get(index);
			println("Arist: " + tempArtist.getName() + " || Number of Listeners: " + tempArtist.getValidUsersSize());
		}
	}


	public void loadArtistVer2()
	{
	    ArtistList = new ArrayList<ArtistData>();
	    ArtistMapID = new HashMap<String,ArtistData>();
	    int artistCounter = 0;
	    //for(int fileIndex = 1; fileIndex <= 56; fileIndex++)
	    for (int fileIndex = 1; fileIndex <= 15; fileIndex++)
	    {
	      String filename = "music360short.txt." +fileIndex;
	  
	      currentFile = loadStrings(filename); 
	      println("Reading File: " + filename);
	      println("Current File Length: " + currentFile.length);
	      int printIndex = 0; 
	      //for(int index=0; index < currentFile.length;index++)
	      for(int index=0; index < currentFile.length; index++)
	      {
	    	  printIndex = index+1;
	          String[] tokens = currentFile[index].split("\t");
	          //bandID  userID #plays
	          //Ian's file: userID bandID bandName #plays
	          //Check to see if this artist exists...
	          if(ArtistMapID.containsKey(tokens[1]))
	          {
	            ArtistData tempArtist = ArtistMapID.get(tokens[1]);
	            //if(UserMapID.containsKey(tokens[0]))
	            if(UserMapID.containsKey(tokens[0]))
	            {

	            		UserData tempUser = UserMapID.get(tokens[0]);
	            		tempArtist.linkUser(tempUser);
		                tempArtist.insertUserCount(tempUser, tokens[3]);
		                tempUser.addArtist(tempArtist);
		                
	            	
	            }
	          }
	          else if(artistCounter < 350)
	          {
	              //New artist found!
	              ArtistData newArtist = new ArtistData(tokens[1]);
	              ArtistMapID.put(tokens[1],newArtist);
	              ArtistList.add(newArtist);
	              artistCounter++;
	              if(UserMapID.containsKey(tokens[0]))
	              {
	            	  UserData tempUser = UserMapID.get(tokens[0]);
	            	  newArtist.linkUser(tempUser);
	            	  newArtist.insertUserCount(tempUser, tokens[3]);
	            	  tempUser.addArtist(newArtist);

	              } 
	          }
	      }
	    }
	}
	
	public void printTest()
	{
		Set<String> keySet = ArtistMapID.keySet();
		println("Number of Artists: " + keySet.size());
	}
	
	public void removeUseless()
	{
		int counter=0;
		for(int index = UserList.size()-1; index >= 0; index--)
		{
			if(UserList.get(index).artistSize() <= 0)
			{
				UserList.remove(index);
				counter++;
			}
		}
		println("Removed: " + counter);
	}

	public void loadArtist()
	{
	    currentFile = loadStrings("top100bandsTop100users.txt");
	    ArtistList = new ArrayList<ArtistData>();
	    ArtistMapID = new HashMap<String,ArtistData>();
	    
	    for(int index=0; index < currentFile.length; index++)
	    {
	        String[] tokens = currentFile[index].split("\t");
	        //bandID  userID #plays
	        //Check to see if this artist exists...
	        if(ArtistMapID.containsKey(tokens[0]))
	        {
	            ArtistData tempArtist = ArtistMapID.get(tokens[0]);
	            if(UserMapID.containsKey(tokens[1]))
	            {
	            	tempArtist.linkUser(UserMapID.get(tokens[1]));
	            	tempArtist.insertUserCount(UserMapID.get(tokens[1]), tokens[2]);
	            }
	            //tempArtist.addUser(tokens[1]);
	            //UserMapID.get(tokens[1]).addArtist(tempArtist);
	            //tempArtist.insertUserCount(tokens[1],tokens[2]);
	        }
	        else
	        {
	            //New artist found!
	            ArtistData newArtist = new ArtistData(tokens[0]);
	            ArtistMapID.put(tokens[0],newArtist);
	            ArtistList.add(newArtist);
	            if(UserMapID.containsKey(tokens[1]))
	            {
	            	newArtist.linkUser(UserMapID.get(tokens[1]));
	            	newArtist.insertUserCount(UserMapID.get(tokens[1]),tokens[2]);
	            }
	            
	            //newArtist.addUser(tokens[1]);
	            //UserMapID.get(tokens[1]).addArtist(newArtist);
	            //newArtist.insertUserCount(tokens[1],tokens[2]);
	        }
	    }
	   
	}//End of Load Artist()
	
	private void loadHeatData() {
		GLOBAL.heatRow2005 = loadStrings("HeatUp2005.txt");
		GLOBAL.heatRow2006 = loadStrings("HeatUp2006.txt");
		GLOBAL.heatRow2007 = loadStrings("HeatUp2007.txt");
		GLOBAL.heatRow2008 = loadStrings("HeatUp2008.txt");
		GLOBAL.heatRow2009 = loadStrings("HeatUp2009.txt");
	}
	
}//End of Radio gaga class.

